#include "wlsdk.h"

#include "WLcJSON.h"
#include "burst_media.h"
#include "burst_module.h"
#include "corp_module.h"
#include "friend_module.h"
#include "group_module.h"
#include "keepalive_module.h"
#include "location_module.h"
#include "login_module.h"
#include "repo.h"
#include "session_module.h"
#include "user_module.h"
#include "wl_utils.h"
#include "wlsdk_define.h"

#include "wl_http_client.h"
#include "tts_client.h"

#ifdef __cplusplus
extern "C" {
#endif

extern unsigned char burst_tone_offline[2131];

typedef struct __stream_client_global {
    wl_bool                initialized;
    wlsdk_message_callback callback;
    wlsdk_enablePA         PA_control_callback;
} sdk_global;

static sdk_global s_sdk_global;

wl_int32 wlsdk_init(wlsdk_message_callback callback, wl_trace_callback trace_callback) {
    wl_trace_regist_callback(trace_callback);
    WLLOGI("wlsdk_init");
    if (!s_sdk_global.initialized) {
        WLcJSON_Hooks hooks;
        wl_int32      ret = wl_core_init();
        if (0 != ret) {
            WLLOGW("wl_core_init fail");
            return ret;
        }
        ret = login_module_init(callback);
        if (0 != ret) {
            WLLOGW("login_module_init fail");
            return ret;
        }
        ret = user_module_init(callback);
        if (0 != ret) {
            WLLOGW("user_module_init fail");
            return ret;
        }
        ret = friend_module_init(callback);
        if (0 != ret) {
            WLLOGW("friend_module_init fail");
            return ret;
        }
        ret = group_module_init(callback);
        if (0 != ret) {
            WLLOGW("group_module_init fail");
            return ret;
        }
        ret = session_module_init(callback);
        if (0 != ret) {
            WLLOGW("session_module_init fail");
            return ret;
        }
        ret = burst_module_init(callback);
        if (0 != ret) {
            WLLOGW("burst_module_init fail");
            return ret;
        }
        ret = location_module_init(callback);
        if (0 != ret) {
            WLLOGW("location_module_init fail");
            return ret;
        }
        ret = corp_module_init(callback);
        if (0 != ret) {
            WLLOGW("corp_module_init fail");
            return ret;
        }
        ret = keepalive_module_init(callback);
        if (0 != ret) {
            WLLOGW("keepalive_module_init fail");
            return ret;
        }
        ret = repo_init();
        if (0 != ret) {
            WLLOGW("repo_init fail");
            return ret;
        }
        ret = wl_http_client_init();
        if (0 != ret) {
            WLLOGW("wl_http_client_init fail");
            return ret;
        }
        ret = tts_client_init();
        if (0 != ret) {
            WLLOGW("tts_client_init fail");
            return ret;
        }

        hooks.malloc_fn = wl_mem_malloc;
        hooks.free_fn   = wl_mem_free;
        WLcJSON_InitHooks(&hooks);

        s_sdk_global.initialized = wl_true;
        s_sdk_global.callback    = callback;
        wl_msleep(100);
        WLLOGI("wlsdk_init success");
        return ret;
    }
    WLLOGI("wlsdk_init success");

    return 0;
}

// wl_int32 wlsdk_init_xip(wlsdk_message_callback callback,
//                         wl_trace_callback      trace_callback,
//                         wl_xip_callback        lock_callbck,
//                         wl_xip_callback        unlock_callback) {
//     wl_int32 ret = -1;
//                wl_set_xip_callback(lock_callbck, unlock_callback);
//     ret = wlsdk_init(callback, trace_callback);
//     return ret;
// }

wl_int32 wlsdk_end(void) {
    if (s_sdk_global.initialized) {
        login_module_end();
        user_module_end();
        friend_module_end();
        group_module_end();
        session_module_end();
        location_module_end();
        corp_module_end();
        keepalive_module_end();
        repo_end();
        wl_http_client_end();
        tts_client_end();
        burst_module_end();
        wl_core_end();
        s_sdk_global.initialized = wl_false;
    }
    return 0;
}

void wlsdk_track_config(wl_bool isopen, wl_uint32 level) {
    wl_trace_config(isopen, level);
}

wl_int32 wlsdk_set_appkey(wl_char* appid, wl_char* appkey) {
    login_appkey msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == appid || wl_null == appkey) {
        WLLOGW("appid or appkey null");
        return -1;
    }
    strncpy(msgdata.appid, appid, sizeof(msgdata.appid));
    msgdata.appid[sizeof(msgdata.appid) - 1] = '\0';
    strncpy(msgdata.appkey, appkey, sizeof(msgdata.appkey));
    msgdata.appkey[sizeof(msgdata.appkey) - 1] = '\0';
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_SET_APPKEY, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_hardware(wl_char*  id,
                            wl_char*  product,
                            wl_char*  imei,
                            wl_char*  imsi,
                            wl_char*  version,
                            wl_uint32 version_number,
                            wl_char*  firmware,
                            wl_uint32 source_type) {
    login_hardware msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == id || wl_null == product || wl_null == imei || wl_null == imsi || wl_null == version) {
        WLLOGW("product or imei or imei or imsi or version is null");
        return -1;
    }
    memset(&msgdata, 0, sizeof(login_hardware));
    strncpy(msgdata.id, id, sizeof(msgdata.id));
    msgdata.id[sizeof(msgdata.id) - 1] = '\0';
    strncpy(msgdata.product, product, sizeof(msgdata.product));
    msgdata.product[sizeof(msgdata.product) - 1] = '\0';
    strncpy(msgdata.imei, imei, sizeof(msgdata.imei));
    msgdata.imei[sizeof(msgdata.imei) - 1] = '\0';
    strncpy(msgdata.imsi, imsi, sizeof(msgdata.imsi));
    msgdata.imsi[sizeof(msgdata.imsi) - 1] = '\0';
    strncpy(msgdata.version, version, sizeof(msgdata.version));
    msgdata.version[sizeof(msgdata.version) - 1] = '\0';
    msgdata.version_number                       = version_number;
    if (wl_null != firmware) {
        strncpy(msgdata.firmware, firmware, sizeof(msgdata.firmware));
        msgdata.firmware[sizeof(msgdata.firmware) - 1] = '\0';
    }
    msgdata.source_type = source_type;
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_SET_HARDWARE, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_resource_version(wl_char* version, wl_uint32 version_number) {
    keepalive_resource_version msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    strncpy(msgdata.version, version, sizeof(msgdata.version));
    msgdata.version[sizeof(msgdata.version) - 1] = '\0';
    msgdata.version_number                       = version_number;
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_RESOURCE_VERSION, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_account(wl_char* account, wl_char* country_code, wl_char* password, wl_bool ismd5pwd) {
    login_account msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == account || wl_null == country_code || wl_null == password) {
        WLLOGW("account or country_code or password is null");
        return -1;
    }
    strncpy(msgdata.account, account, sizeof(msgdata.account));
    msgdata.account[sizeof(msgdata.account) - 1] = '\0';
    strncpy(msgdata.country_code, country_code, sizeof(msgdata.country_code));
    msgdata.country_code[sizeof(msgdata.country_code) - 1] = '\0';
    strncpy(msgdata.password, password, sizeof(msgdata.password));
    msgdata.password[sizeof(msgdata.password) - 1] = '\0';
    msgdata.ismd5pwd                               = ismd5pwd;
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_SET_ACCOUNT, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_network(wl_uint32 simid, wl_uint32 pdpid, wl_uint32 state) {
    keepalive_network msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    msgdata.simid = simid;
    msgdata.pdpid = pdpid;
    msgdata.state = state;
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_NETWORK, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_login_url(wl_char* url) {
    login_url msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == url) {
        WLLOGW("url is null");
        return -1;
    }
    strncpy(msgdata.url, url, sizeof(msgdata.url));
    msgdata.url[sizeof(msgdata.url) - 1] = '\0';
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_SET_LOGIN_URL, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_web_server(wl_char* host, wl_uint16 port) {
    login_server msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == host) {
        WLLOGW("host is null");
        return -1;
    }
    strncpy(msgdata.host, host, sizeof(msgdata.host));
    msgdata.host[sizeof(msgdata.host) - 1] = '\0';
    msgdata.port                           = port;
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_SET_WEB_SERVER, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_record_drop_duration(wl_uint32 duration) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (!AUDIO_VOIP_SUPPORT) {
        duration = 20;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_RECORD_DROP_DURATION, &duration, sizeof(wl_uint32));
}

wl_int32 wlsdk_set_record_end_drop_duration(wl_uint32 duration) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_RECORD_END_DROP_DURATION, &duration, sizeof(wl_uint32));
}

wl_int32 wlsdk_get_server_state(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_GET_SERVER_STATE, wl_null, 0);
}

// login
wl_int32 wlsdk_login(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_LOGIN, wl_null, 0);
}

wl_int32 wlsdk_logout(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_LOGOUT, wl_null, 0);
}

wl_int32 wlsdk_set_voip_auto_accept(wl_bool auto_accept, wl_uint32 delay_ms) {
    burst_voip_auto_accept voip_auto_accept;
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    voip_auto_accept.auto_accept = auto_accept;
    voip_auto_accept.delay_ms    = delay_ms;
    return wl_core_send_message(
        WL_MODULE_BURST, BURST_MSG_SET_VOIP_AUTO_ACCEPT, &voip_auto_accept, sizeof(voip_auto_accept));
}

wl_int32 wlsdk_get_login_state(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_GET_LOGIN_STATE, wl_null, 0);
}

wl_int32 wlsdk_get_extension_state(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_GET_EXTENSION_STATE, wl_null, 0);
}

wl_int32 wlsdk_answer_bind_extension(wl_uint32 status) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOGIN, LOGIN_MSG_ANSWER_BIND_EXTENSION, &status, sizeof(wl_uint32));
}

// user
wl_int32 wlsdk_get_selfinfo(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_USER, USER_MSG_GET_SELFINFO, wl_null, 0);
}

wl_int32 wlsdk_get_user_config(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_USER, USER_MSG_GET_USER_CONFIG, wl_null, 0);
}

// session
wl_int32 wlsdk_get_sessions(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_SESSION, SESSION_MSG_GET_SESSIONS, wl_null, 0);
}

wl_int32 wlsdk_remove_session(wl_uint64 sessionid, wl_uint32 sessiontype) {
    session_sessioninfo msgdata;
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    msgdata.sessionid   = sessionid;
    msgdata.sessiontype = sessiontype;
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_REMOVE_SESSION, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_close_session(wl_uint64 sessionid, wl_uint32 sessiontype) {
    session_sessioninfo msgdata;
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    msgdata.sessionid   = sessionid;
    msgdata.sessiontype = sessiontype;
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_CLOSE_SESSION, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_set_burst_session(wl_uint64 sessionid, wl_uint32 sessiontype) {
    session_sessioninfo msgdata;
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    msgdata.sessionid   = sessionid;
    msgdata.sessiontype = sessiontype;
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_SET_BURST_SESSION, &msgdata, sizeof(msgdata));
}

wl_int32 wlsdk_session_burst_request(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_REQUEST, wl_null, 0);
}

wl_int32 wlsdk_session_burst_release(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_RELEASE, wl_null, 0);
}

wl_int32 wlsdk_session_burst_release_audio_drop(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return burst_module_burst_release_audio_drop();
}

wl_int32 wlsdk_session_playback(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_PLAYBACK, wl_null, 0);
}

// group
wl_int32 wlsdk_group_get_groups(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_GROUP, GROUP_MSG_GET_GROUPS, wl_null, 0);
}

// friend
wl_int32 wlsdk_friend_get_friends(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_FRIEND, FRIEND_MSG_GET_FRIENDS, wl_null, 0);
}

// location
wl_int32 wlsdk_set_yby_location(wl_char* content) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == content) {
        WLLOGW("content is null");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOCATION, LOCATION_MSG_SET_YBY_LOCATION, content, strlen(content) + 1);
}

wl_int32 wlsdk_set_gps_location(wlsdk_location* location) {
    location_set_location msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == location) {
        WLLOGW("location is null");
        return -1;
    }
    memset(&msgdata, 0, sizeof(location_set_location));
    msgdata.isgps = wl_true;
    memcpy(&msgdata.location, location, sizeof(wlsdk_location));
    if (0 == location->type) {
        wl_wgs84togcj02(
            location->latitude, location->longitude, &msgdata.location.latitude, &msgdata.location.longitude);
        msgdata.location.type = 1;
    }
    return wl_core_send_message(WL_MODULE_LOCATION, LOCATION_MSG_SET_LOCATION, &msgdata, sizeof(location_set_location));
}

wl_int32 wlsdk_set_lbs_location(wlsdk_lbs* lbs) {
    location_set_lbs msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == lbs) {
        WLLOGW("lbs is null");
        return -1;
    }
    memset(&msgdata, 0, sizeof(location_set_lbs));
    memcpy(&msgdata.lbs, lbs, sizeof(wlsdk_lbs));
    return wl_core_send_message(WL_MODULE_LOCATION, LOCATION_MSG_SET_LBS, &msgdata, sizeof(location_set_lbs));
}

wl_int32 wlsdk_open_sos(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOCATION, LOCATION_MSG_OPEN_SOS, wl_null, 0);
}

wl_int32 wlsdk_close_sos(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_LOCATION, LOCATION_MSG_CLOSE_SOS, wl_null, 0);
}

wl_int32 wlsdk_check_version(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_CHECK_VERSION, wl_null, 0);
}

wl_int32 wlsdk_alarm_power(wl_int32 percent) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_ALARM_POWER, &percent, sizeof(wl_int32));
}

wl_int32 wlsdk_battery_update(wl_int32 percent) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_BATTERY_UPDATE, &percent, sizeof(wl_int32));
}

wl_int32 wlsdk_set_heartbeat_interval(wl_int32 interval) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_HEARTBEAT_INTERVAL, &interval, sizeof(wl_int32));
}

wl_int32 wlsdk_set_fast_heartbeat(wl_bool enable) {
    wl_int32 interval = 60;
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (!enable) {
        interval = 300;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_HEARTBEAT_INTERVAL, &interval, sizeof(wl_int32));
}

wl_int32 wlsdk_set_memory_threshold(wl_int32 threshold) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_MEMORY_THRESHOLD, &threshold, sizeof(wl_int32));
}

wl_int32 wlsdk_set_memory_alarm_reboot_hour(wl_int32 hour) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(
        WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_MEMORY_ALARM_REBOOT_HOUR, &hour, sizeof(wl_int32));
}

// tts
wl_int32 wlsdk_tts(wl_char* text) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_TTS, text, strlen(text) + 1);
}

wl_int32 wlsdk_play_audio(wl_char* data, wl_uint32 datalen) {
    burst_realtime_audio* msgdata = wl_null;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    msgdata = (burst_realtime_audio*)wl_malloc(sizeof(burst_realtime_audio) + datalen);
    if (wl_null == msgdata) {
        WLLOGW("malloc fail");
        return -1;
    }
    memcpy(msgdata->data, data, datalen);
    msgdata->datalen = datalen;
    msgdata->rate    = 0;
    if (0 > wl_core_send_message(
            WL_MODULE_BURST, BURST_MSG_REALTIME_AUDIO, msgdata, sizeof(burst_realtime_audio) + datalen)) {
        wl_free(msgdata);
        return -1;
    }
    wl_free(msgdata);
    return 0;
}

wl_int32 wlsdk_play_pcm(wl_char* data, wl_uint32 datalen, wl_uint32 rate) {
    burst_realtime_audio* msgdata = wl_null;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (8000 != rate && 16000 != rate) {
        WLLOGW("rate %d invalid", rate);
        return -1;
    }
    msgdata = (burst_realtime_audio*)wl_malloc(sizeof(burst_realtime_audio) + datalen);
    if (wl_null == msgdata) {
        WLLOGW("malloc fail");
        return -1;
    }
    memcpy(msgdata->data, data, datalen);
    msgdata->datalen    = datalen;
    msgdata->iscompress = wl_false;
    msgdata->rate       = rate;
    if (0 > wl_core_send_message(
            WL_MODULE_BURST, BURST_MSG_REALTIME_AUDIO, msgdata, sizeof(burst_realtime_audio) + datalen)) {
        wl_free(msgdata);
        return -1;
    }
    wl_free(msgdata);
    return 0;
}

wl_int32 wlsdk_play_pcm_compress(wl_char* data, wl_uint32 datalen, wl_uint32 rate) {
    burst_realtime_audio* msgdata         = wl_null;
    wl_uint32             media_audio_len = 0;
    wl_uint32             frames_count    = 0;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    // 先压缩成OPUS
    if (8000 != rate && 16000 != rate) {
        WLLOGW("rate %d invalid", rate);
        return -1;
    }
    burst_media_count_pcm_audio(datalen, rate, &media_audio_len, &frames_count);
    msgdata = (burst_realtime_audio*)wl_malloc(sizeof(burst_realtime_audio) + media_audio_len);
    if (wl_null == msgdata) {
        WLLOGW("malloc fail");
        return -1;
    }
    WLLOGI("pcm media_audio_len %d frames_count %d datalen %d", media_audio_len, frames_count, datalen);
    if (0 == burst_media_convert_pcm_audio_to_media_audio(data, datalen, rate, msgdata->data, &media_audio_len)) {
        msgdata->rate       = rate;
        msgdata->datalen    = media_audio_len;
        msgdata->iscompress = wl_true;
        if (0 > wl_core_send_message(
                WL_MODULE_BURST, BURST_MSG_REALTIME_AUDIO, msgdata, sizeof(burst_realtime_audio) + msgdata->datalen)) {
            wl_free(msgdata);
            return -1;
        }
    } else {
        WLLOGW("burst_media_convert_pcm_audio_to_media_audio fail");
        wl_free(msgdata);
        return -1;
    }
    wl_free(msgdata);
    return 0;
}

wl_int32 wlsdk_audio_pause(wl_int32 duration) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_PAUSE, &duration, sizeof(wl_int32));
}

wl_int32 wlsdk_audio_resume(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_RESUME, wl_null, 0);
}

wl_int32 wlsdk_voip_invite(wl_uint32 userId) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_VOIP_INVITE, &userId, sizeof(wl_int32));
}

wl_int32 wlsdk_voip_accept(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_VOIP_ACCEPT, wl_null, 0);
}

wl_int32 wlsdk_voip_hangup(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_VOIP_HANGUP, wl_null, 0);
}

wl_int32 wlsdk_button_press(wl_int32 idx) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_BUTTON_PRESS, &idx, sizeof(wl_int32));
}

wl_int32 wlsdk_button_release(wl_int32 idx) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_BUTTON_RELEASE, &idx, sizeof(wl_int32));
}

wl_int32 wlsdk_report_reboot(wl_int32 memory) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_REPORT_REBOOT, &memory, sizeof(wl_int32));
}

wl_int32 wlsdk_report_reset_modem(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_REPORT_RESET_MODEM, wl_null, 0);
}

wl_int32 wlsdk_set_ota_status(wl_int32 status) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_KEEPALIVE, KEEPALIVE_MSG_SET_OTA_STATUS, &status, sizeof(wl_int32));
}

wl_int32 wlsdk_get_lbs_location(wlsdk_lbs* lbs) {
    location_get_lbs msgdata;

    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    if (wl_null == lbs) {
        WLLOGW("lbs is null");
        return -1;
    }
    memset(&msgdata, 0, sizeof(location_get_lbs));
    memcpy(&msgdata.lbs, lbs, sizeof(wlsdk_lbs));
    return wl_core_send_message(WL_MODULE_LOCATION, LOCATION_MSG_GET_LBS, &msgdata, sizeof(location_get_lbs));
}

wl_int32 wlsdk_set_tmp_session_keeptime(wl_int32 duration) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_SESSION, SESSION_MSG_TMP_SESSION_KEEPTIME, &duration, sizeof(wl_int32));
}

wl_int32 wlsdk_burst_session_switch(void) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return -1;
    }
    return wl_core_send_message(WL_MODULE_BURST, BURST_MSG_BURST_SWITCH, wl_null, 0);
}

void wlsdk_set_PA_control_callback(wlsdk_enablePA callback) {
    if (!s_sdk_global.initialized) {
        WLLOGW("sdk not init");
        return;
    }
    s_sdk_global.PA_control_callback = callback;
}

wlsdk_enablePA wlsdk_get_PA_control_callback() {
    if (!s_sdk_global.initialized) {
        return NULL;
    }

    return s_sdk_global.PA_control_callback;
}

#ifdef __cplusplus
}
#endif
